{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "e53b5877-1fd4-43a6-883b-fddcd470d683",
   "metadata": {},
   "outputs": [],
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 161,
   "id": "b8ed1474-36fc-4f1a-abe0-90a35129564a",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "from os.path import exists\n",
    "from torch import nn\n",
    "import torchvision\n",
    "import copy\n",
    "import PIL.Image as Image\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import os\n",
    "from jsputils import paths, nsdorg, plotting, encoding, nnutils, selectivity, validation, lesioning\n",
    "from fastprogress import progress_bar\n",
    "from IPython.core.debugger import set_trace"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "36d6a566-c56f-498c-8547-638b5d7addb6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1584"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# vpnl-floc\n",
    "# classic-categ\n",
    "# mc8-lummatched\n",
    "# mc8-shined\n",
    "\n",
    "class ImageSet:\n",
    "    def __init__(self, image_set_name, transforms = None):\n",
    "        \n",
    "        self.image_set_name = image_set_name\n",
    "        self.image_folder = f'{paths.image_set_dir()}/{self.image_set_name}'\n",
    "        self.transforms = transforms\n",
    "        \n",
    "        if image_set_name == 'vpnl-floc':\n",
    "            self.categ_nimg = 144\n",
    "            self.floc_subdirs = np.array(['adult','body','car','child','corridor','house',\n",
    "                                                       'instrument','limb','number','scrambled','word'])\n",
    "            self.floc_domains = np.array(['faces','bodies','objects','scenes','characters','scrambled'])\n",
    "            self.domain_colors = np.array(['red','dodgerblue','orange','limegreen','blueviolet','lightgray'])\n",
    "            self.subdir_domain_ref = np.array([0,1,2,0,3,3,2,1,4,5,4])\n",
    "            \n",
    "        elif image_set_name == 'classic-categ':\n",
    "            self.categ_nimg = 80\n",
    "            self.floc_subdirs = np.array(['1-Faces','2-Bodies','3-Scenes','4-Words',\n",
    "                                          '5-Objects','6-ScrambledObjects','7-ScrambledWords'])\n",
    "            self.floc_domains = np.array(['faces','bodies','objects','scenes','characters','scrambled'])\n",
    "            self.domain_colors = np.array(['red','dodgerblue','orange','limegreen','blueviolet','lightgray'])\n",
    "            self.subdir_domain_ref = np.array([0,1,2,3,4,5,5])\n",
    "            \n",
    "        for subdir in os.listdir(self.image_folder):\n",
    "            if os.path.isdir(subdir):\n",
    "                assert(len(os.listdir(f'{self.image_folder}/{subdir}')) == self.categ_nimg)\n",
    "            \n",
    "        self.img_domain_indices = np.repeat(self.subdir_domain_ref, self.categ_nimg)\n",
    "        \n",
    "        self.load_images()\n",
    "            \n",
    "    def load_images(self):\n",
    "        # Load images from the folder using torchvision and apply transforms\n",
    "        self.images = torchvision.datasets.ImageFolder(self.image_folder, transform = self.transforms)\n",
    "    \n",
    "    def plot_domain_labels(self):\n",
    "        plt.figure()\n",
    "        plt.plot(self.img_domain_indices)\n",
    "        plt.yticks(np.arange(len(self.floc_domains)),self.floc_domains);\n",
    "        plt.xlabel('floc img indices')\n",
    "        plt.title(f'domain of each floc image: {self.image_set_name}');\n",
    "        \n",
    "        \n",
    "test = ImageSet('vpnl-floc')\n",
    "len(test.images)\n",
    "#test.load_images()\n",
    "#test.images[0][0]\n",
    "#test.plot_domain_labels()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c21b9eaf-aa24-4506-9897-457933d103e3",
   "metadata": {},
   "outputs": [],
   "source": [
    "class DataLoaderFFCV:\n",
    "    def __init__(self, partition, device = 'cuda:0', batch_size = 512, num_workers = 64):\n",
    "        self.partition = partition\n",
    "        self.device = device\n",
    "        self.batch_size = batch_size\n",
    "        self.num_workers = num_workers\n",
    "           \n",
    "        if self.partition == 'train':\n",
    "            pass\n",
    "        elif self.partition == 'val':\n",
    "            self.data_loader = validation.create_val_loader(paths.ffcv_imagenet1k_valset(), \n",
    "                                                            self.device,\n",
    "                                                            self.num_workers, \n",
    "                                                            self.batch_size)\n",
    "\n",
    "\n",
    "#     def extract_activations(self, layer_name):\n",
    "#         # Extract activations from the specified layer of the model for the given image set\n",
    "#         pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "a4908a88-d98b-422f-b82a-c492b3f9e397",
   "metadata": {},
   "outputs": [],
   "source": [
    "class DNNModel:\n",
    "    def __init__(self, model_name):\n",
    "                         \n",
    "        self.model, self.transforms, self.state_dict, self.is_categ_supervised, self.model_name = nnutils.load_model(model_name)\n",
    "                 \n",
    "        self.layer_names, self.layer_dims = nnutils.get_layer_names_and_dims(self.model)\n",
    "        self.formatted_layer_names = None\n",
    "\n",
    "    def find_selective_units(self, localizer_image_set, FDR_p = 0.05, overwrite = False, verbose = False):\n",
    "        \n",
    "        # Define the indices of category-selective units using localizer images\n",
    "        floc_imageset = ImageSet(localizer_image_set, transforms = self.transforms)\n",
    "        \n",
    "        self.selective_units = selectivity.run_dnn_localizer_procedure(self, floc_imageset, FDR_p, overwrite, verbose)\n",
    "        \n",
    "    def get_imagenet_accs(self, topk = 5): \n",
    "        \n",
    "        ValLoader = DataLoaderFFCV('val')\n",
    "        \n",
    "        self.imagenet_accs = validation.get_imagenet_class_accuracies(copy.deepcopy(self.model).half().to(ValLoader.device),\n",
    "                                                                      ValLoader.data_loader,\n",
    "                                                                      ValLoader.device, topk = topk)\n",
    "            \n",
    "            \n",
    "    def train_linear_probe(self):\n",
    "        # Train a linear ImageNet probe for self-supervised models\n",
    "        pass\n",
    "\n",
    "    def assess_lesioning_impact(self):\n",
    "        # Assess the impact of lesioning selective units on the model's ImageNet performance\n",
    "        pass\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b4ca6710-14cc-427d-ae09-d92a3fb61bba",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "DNN = DNNModel('alexnet-dropout-0.5')\n",
    "DNN.find_selective_units('vpnl-floc')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "045eed1e-74ae-4d95-8370-9a5f417b24e2",
   "metadata": {},
   "outputs": [],
   "source": [
    "DNN.selective_units['floc_domains']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9b733e9c-886e-4440-8abb-93f4b5d4a88a",
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "#DNN.get_selective_unit_val_acts('vpnl-floc')\n",
    "#DNN.find_selective_units('vpnl-floc')\n",
    "\n",
    "DNN.get_imagenet_accs(topk = 5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "01389543-f8c7-43e7-92aa-2c889a1e0708",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "51d3f36e-7a67-4d10-8825-f78dad6344b1",
   "metadata": {},
   "outputs": [],
   "source": [
    "class LesionModel(DNNModel):\n",
    "    def __init__(self, DNNModel, device):\n",
    "        \n",
    "        self.model = DNNModel.model\n",
    "        if hasattr(DNNModel,'selective_units'):\n",
    "            self.selective_units = DNNModel.selective_units\n",
    "        self.device = device\n",
    "        \n",
    "        # initialize lesioning model using modules from source network\n",
    "        masks = dict()\n",
    "        masks['apply'] = False\n",
    "        self.model = lesioning.LesionNet(self.model, masks).eval().to(self.device)\n",
    "        \n",
    "        self.layer_dims = lesioning.get_layer_dims(self.model, self.device)\n",
    "    \n",
    "        \n",
    "    def apply_randomized_lesions(self, lsn_layer, p = 0.5):\n",
    "        \n",
    "        self.model.masks = lesioning.get_random_lesioning_masks(self.model, \n",
    "                                                          self.layer_dims, \n",
    "                                                          lsn_layer, \n",
    "                                                          self.device, \n",
    "                                                          p)\n",
    "        \n",
    "    def remove_randomized_lesions(self):\n",
    "        masks = dict()\n",
    "        masks['apply'] = False\n",
    "        self.model.masks = masks\n",
    "                \n",
    "    def get_imagenet_accs(self, topk = 5): \n",
    "        \n",
    "        ValLoader = DataLoaderFFCV('val')\n",
    "        \n",
    "        self.imagenet_accs = validation.get_imagenet_class_accuracies(copy.deepcopy(self.model).half().to(ValLoader.device),\n",
    "                                                                      ValLoader.data_loader,\n",
    "                                                                      ValLoader.device, topk = topk)\n",
    "    \n",
    "    def get_selective_unit_acts(self):\n",
    "        \n",
    "        assert(hasattr(self, 'selective_units'))\n",
    "            \n",
    "        ValLoader = DataLoaderFFCV('val')\n",
    "        \n",
    "        print(self.model.layer_names)\n",
    "        \n",
    "        self.selective_unit_acts = validation.get_selective_unit_acts(copy.deepcopy(self.model).half().to(ValLoader.device),\n",
    "                                                                      copy.deepcopy(self.selective_units),\n",
    "                                                                      list(self.selective_units['faces'].keys()),\n",
    "                                                                      ValLoader.data_loader,\n",
    "                                                                      ValLoader.device)\n",
    "        \n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "06801f58-4fa3-484a-9b6e-94d8c882e111",
   "metadata": {},
   "outputs": [],
   "source": [
    "#LSN.selective_units['faces']\n",
    "# torch.cuda.empty_cache()\n",
    "# del LSN\n",
    "# gc.collect()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "99c31618-aa7e-476f-8e85-513199d664a1",
   "metadata": {},
   "outputs": [],
   "source": [
    "#x = torch.ones(1,3,224,224) * 100\n",
    "LSN = LesionModel(DNN, 'cuda:0')\n",
    "LSN.model.return_acts = False\n",
    "LSN.model.masks['apply'] = False\n",
    "#LSN.get_selective_unit_acts()\n",
    "#LSN.apply_randomized_lesions('relu6', p = 0.7)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ad006760-c2f5-413d-b75a-d95589b24e8d",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = list(DNN.selective_units['faces'].keys())\n",
    "b = list(LSN.model.layer_names)\n",
    "\n",
    "print(a,b)\n",
    "print(len(a), len(b))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0b95c70f-a1ab-42ce-9904-831ea69d9478",
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "# layer_mapping = dict()\n",
    "# nnutils.alexnet_layer_str_format(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7075cfce-7f18-4541-99cd-6962b91a41bb",
   "metadata": {},
   "outputs": [],
   "source": [
    "LSN.get_imagenet_accs(topk=5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f143ed0c-04f2-46f9-9820-fba256e02244",
   "metadata": {},
   "outputs": [],
   "source": [
    "# LSN.model.return_acts = False\n",
    "# LSN.apply_randomized_lesions('relu6', p = 0.99)\n",
    "LSN.remove_randomized_lesions()\n",
    "\n",
    "# a = LSN.model(x).detach().numpy().squeeze()\n",
    "\n",
    "# plt.plot(a);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c2438911-654a-4da7-8152-2d4f08ee054b",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(np.mean(DNN.imagenet_accs))\n",
    "print(np.mean(LSN.imagenet_accs))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 148,
   "id": "1b432450-422e-404f-a54e-b30f93fab82a",
   "metadata": {},
   "outputs": [],
   "source": [
    "class fMRISubject:\n",
    "    def __init__(self, subj, space, beta_version):\n",
    "        self.subj = subj\n",
    "        self.space = space\n",
    "        self.beta_version = beta_version\n",
    "        self.betadir = f'{paths.nsd()}/nsddata_betas/ppdata/{self.subj}/{self.space}/{self.beta_version}'   \n",
    "        self.processed_datadir = f'{paths.brain_region_savedir()}/{self.subj}'\n",
    "        os.makedirs(self.processed_datadir,exist_ok=True)\n",
    "\n",
    "        if self.space == 'nativesurface':\n",
    "            self.hemis = ['lh', 'rh']\n",
    "        elif self.space == 'func1pt8mm':\n",
    "            self.hemis = ['full']\n",
    "        \n",
    "        if not hasattr(self, 'metadata'):\n",
    "            self.get_voxel_metadata()\n",
    "    \n",
    "    def get_voxel_metadata(self):\n",
    "        self.metadata = nsdorg.load_voxel_info(self.subj, self.space, self.beta_version)\n",
    "        \n",
    "    def plot_data(self, data, title):\n",
    "        plotting.plot_ROI_flatmap(self.subj, self.space, title, data, vmin = np.nanmin(data),\n",
    "                                  vmax=np.nanmax(data),colorbar=True)\n",
    "        \n",
    "            \n",
    "    def load_fmri_data(self):\n",
    "        # Load fMRI data from the given path and preprocess it\n",
    "        pass\n",
    "\n",
    "    def find_brain_regions(self):\n",
    "        # Find brain regions with selectivities and add them to self.brain_regions\n",
    "        pass\n",
    "    \n",
    "class BrainRegion(fMRISubject):\n",
    "    def __init__(self, subj, roi, ncsnr_threshold, plot = True):\n",
    "        \n",
    "        self.savefn = f'{subj.processed_datadir}/{subj.space}_{roi}.npy'\n",
    "        \n",
    "        if exists(self.savefn):\n",
    "            print('betas already saved. loading...')\n",
    "            self.betas = np.load(self.savefn,allow_pickle=True).item().betas\n",
    "            self.rep_cocos = self.betas['rep_cocos']\n",
    "            self.included_voxel_idx = self.betas['included_voxel_idx']\n",
    "        \n",
    "        if hasattr(subj,'metadata'):\n",
    "            self.metadata = subj.metadata\n",
    "        super().__init__(subj.subj, subj.space, subj.beta_version)\n",
    "        self.roi = roi\n",
    "        self.ncsnr_threshold = ncsnr_threshold\n",
    "\n",
    "        self.roi_indices = nsdorg.get_voxel_group(self.subj, self.space, self.roi,\n",
    "                                                  self.ncsnr_threshold, self.metadata, plot = plot)\n",
    "        self.get_ncsnr()\n",
    "\n",
    "    def get_ncsnr(self):\n",
    "        \n",
    "        self.ncsnr = []\n",
    "        if self.space == 'nativesurface':\n",
    "            self.ncsnr = np.concatenate((self.metadata[0]['lh.ncsnr'].values,\n",
    "                                         self.metadata[1]['rh.ncsnr'].values))\n",
    "\n",
    "            self.ncsnr[np.logical_not(self.roi_indices['full'])] = np.nan\n",
    "        elif self.space == 'func1pt8mm':\n",
    "            raise ValueError('not implemented yet')\n",
    "        \n",
    "    def load_betas(self):\n",
    "        \n",
    "        if not hasattr(self, 'betas'):\n",
    "            self.betas, _, self.included_voxel_idx, self.rep_cocos = nsdorg.load_betas(self.subj, \n",
    "                                                                                 self.space, \n",
    "                                                                                voxel_group = self.roi,\n",
    "                                                                                ncsnr_threshold = self.ncsnr_threshold,\n",
    "                                                                                plot=False\n",
    "                                                                                )\n",
    "            \n",
    "            self.betas['rep_cocos'] = self.rep_cocos\n",
    "            self.betas['included_voxel_idx'] = self.included_voxel_idx\n",
    "            self.save()\n",
    "            \n",
    "    def load_train_test_data(self, train_imageset, test_imageset):\n",
    "        print('loading train and test data')\n",
    "        self.image_data, self.brain_data = nsdorg.get_NSD_train_test_images_and_betas(subj = self.subj,\n",
    "                                                                                      space = self.space,\n",
    "                                                                                      subj_betas = self.betas,\n",
    "                                                                                      rep_cocos = self.rep_cocos,\n",
    "                                                                                      train_imageset = train_imageset,\n",
    "                                                                                      test_imageset = test_imageset,\n",
    "                                                                                      mean = False)\n",
    "    def get_ncsnr_mask(self, threshold):\n",
    "        self.ncsnr_threshold_ = threshold\n",
    "        self.mask = self.ncsnr[self.included_voxel_idx['full']] > self.ncsnr_threshold_\n",
    "\n",
    "    def save(self):\n",
    "        np.save(self.savefn, self, allow_pickle=True)\n",
    "\n",
    "\n",
    "#class NoiseCeiling: \n",
    "#    def __init__(self, Br, \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "97bd8f69-c918-4cc4-aac9-2162b2f793b3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='4' class='' max='8' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      50.00% [4/8 19:52&lt;19:52]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(30000, 1064)\n",
      "(30000, 485)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='40' class='' max='40' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [40/40 00:12&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='40' class='' max='40' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [40/40 00:05&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(10000, 3, 1064)\n",
      "(10000, 3, 485)\n",
      "(30000, 2180)\n",
      "(30000, 1727)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='40' class='' max='40' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [40/40 00:26&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='40' class='' max='40' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [40/40 00:21&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(10000, 3, 2180)\n",
      "(10000, 3, 1727)\n",
      "(30000, 4721)\n",
      "(30000, 7649)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='40' class='' max='40' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [40/40 00:57&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='40' class='' max='40' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [40/40 01:35&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(10000, 3, 4721)\n",
      "(10000, 3, 7649)\n",
      "(30000, 2809)\n",
      "(30000, 864)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='40' class='' max='40' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [40/40 00:34&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='40' class='' max='40' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [40/40 00:10&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(10000, 3, 2809)\n",
      "(10000, 3, 864)\n",
      "(30000, 443)\n",
      "(30000, 1084)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='40' class='' max='40' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [40/40 00:05&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='40' class='' max='40' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [40/40 00:12&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(10000, 3, 443)\n",
      "(10000, 3, 1084)\n",
      "(30000, 1959)\n",
      "(30000, 2467)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='40' class='' max='40' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [40/40 00:23&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='40' class='' max='40' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [40/40 00:30&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(10000, 3, 1959)\n",
      "(10000, 3, 2467)\n",
      "(30000, 6960)\n",
      "(30000, 8000)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='40' class='' max='40' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [40/40 01:25&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='40' class='' max='40' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [40/40 01:39&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(10000, 3, 6960)\n",
      "(10000, 3, 8000)\n",
      "(30000, 876)\n",
      "(30000, 643)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='40' class='' max='40' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [40/40 00:10&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='40' class='' max='40' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [40/40 00:07&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(10000, 3, 876)\n",
      "(10000, 3, 643)\n",
      "(24000, 785)\n",
      "(24000, 1743)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='32' class='' max='32' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [32/32 00:07&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(30000, 785)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='32' class='' max='32' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [32/32 00:17&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(30000, 1743)\n",
      "(10000, 3, 785)\n",
      "(10000, 3, 1743)\n",
      "(24000, 2471)\n",
      "(24000, 3236)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='32' class='' max='32' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [32/32 00:24&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(30000, 2471)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='32' class='' max='32' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [32/32 00:32&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(30000, 3236)\n",
      "(10000, 3, 2471)\n",
      "(10000, 3, 3236)\n",
      "(24000, 7676)\n",
      "(24000, 7521)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='32' class='' max='32' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [32/32 01:15&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(30000, 7676)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='32' class='' max='32' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [32/32 01:13&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(30000, 7521)\n",
      "(10000, 3, 7676)\n",
      "(10000, 3, 7521)\n",
      "(24000, 3046)\n",
      "(24000, 998)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='32' class='' max='32' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [32/32 00:29&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(30000, 3046)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='32' class='' max='32' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [32/32 00:09&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(30000, 998)\n",
      "(10000, 3, 3046)\n",
      "(10000, 3, 998)\n",
      "(22500, 1089)\n",
      "(22500, 793)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='30' class='' max='30' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [30/30 00:09&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(30000, 1089)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='30' class='' max='30' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [30/30 00:07&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(30000, 793)\n",
      "(10000, 3, 1089)\n",
      "(10000, 3, 793)\n",
      "(22500, 2115)\n",
      "(22500, 1856)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='30' class='' max='30' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [30/30 00:19&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(30000, 2115)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='30' class='' max='30' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [30/30 00:17&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(30000, 1856)\n",
      "(10000, 3, 2115)\n",
      "(10000, 3, 1856)\n",
      "(22500, 7568)\n",
      "(22500, 8197)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='30' class='' max='30' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [30/30 01:09&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(30000, 7568)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='30' class='' max='30' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [30/30 01:15&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(30000, 8197)\n",
      "(10000, 3, 7568)\n",
      "(10000, 3, 8197)\n",
      "(22500, 1722)\n",
      "(22500, 1314)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='30' class='' max='30' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [30/30 00:15&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(30000, 1722)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='30' class='' max='30' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [30/30 00:11&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(30000, 1314)\n",
      "(10000, 3, 1722)\n",
      "(10000, 3, 1314)\n",
      "(30000, 531)\n",
      "(30000, 995)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='40' class='' max='40' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [40/40 00:06&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='40' class='' max='40' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [40/40 00:11&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(10000, 3, 531)\n",
      "(10000, 3, 995)\n",
      "(30000, 2655)\n",
      "(30000, 2482)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='40' class='' max='40' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [40/40 00:33&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='40' class='' max='40' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [40/40 00:33&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(10000, 3, 2655)\n",
      "(10000, 3, 2482)\n",
      "(30000, 9411)\n",
      "(30000, 10685)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='40' class='' max='40' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      100.00% [40/40 01:58&lt;00:00]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<style>\n",
       "    /* Turns off some styling */\n",
       "    progress {\n",
       "        /* gets rid of default border in Firefox and Opera. */\n",
       "        border: none;\n",
       "        /* Needs to be in here for Safari polyfill so background images work as expected. */\n",
       "        background-size: auto;\n",
       "    }\n",
       "    progress:not([value]), progress:not([value])::-webkit-progress-bar {\n",
       "        background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);\n",
       "    }\n",
       "    .progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {\n",
       "        background: #F44336;\n",
       "    }\n",
       "</style>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "    <div>\n",
       "      <progress value='37' class='' max='40' style='width:300px; height:20px; vertical-align: middle;'></progress>\n",
       "      92.50% [37/40 02:02&lt;00:09]\n",
       "    </div>\n",
       "    "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "for subj in progress_bar([f'subj0{s}' for s in range(1,9)]):\n",
    "    NSDsubj = fMRISubject(subj,\n",
    "                         'nativesurface',\n",
    "                         'betas_fithrf_GLMdenoise_RR')\n",
    "    \n",
    "    for roi in ['FFA-1','PPA','EBA','VWFA-1']:\n",
    "\n",
    "        ROI = BrainRegion(NSDsubj, roi, 0, plot = False)\n",
    "        ROI.load_betas()\n",
    "    \n",
    "#OTC.load_train_test_data(train_imageset = 'nonshared1000-3rep-batch1', test_imageset = 'special515')\n",
    "#FFA.betas['lh'].shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 151,
   "id": "f3a9c7bc-12bd-4d2a-b755-d86b2040ae38",
   "metadata": {},
   "outputs": [],
   "source": [
    "FFA.get_ncsnr_mask(threshold = 0.3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 153,
   "id": "aa62380d-d5a7-42b1-8a7a-ba20949ddc18",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1549"
      ]
     },
     "execution_count": 153,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(FFA.mask)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 110,
   "id": "6bf5bda2-c08a-46d5-a5f3-3b71517f8305",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(10000, 3, 1064)"
      ]
     },
     "execution_count": 110,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#subj01.plot_data(OTC.ncsnr, 'OTC')\n",
    "FFA.betas['lh'].shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "id": "b30a8eb6-ff2e-46c1-a7e9-b271edf6ffe5",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.load('/home/jovyan/work/DataLocal-w/NSD_processed_data/subj01/nativesurface_FFA-1.npy',allow_pickle=True).item()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "id": "b65aa453-525c-4222-8e36-4d475ad65fe7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(10000, 3, 1064)"
      ]
     },
     "execution_count": 105,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a.betas['lh'].shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7855d6c7-3fcf-4e88-8afb-8653da329327",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7cea2b71-4b01-45e9-83d6-9d1280d4bf2b",
   "metadata": {},
   "outputs": [],
   "source": [
    "class BrainModelComparison:\n",
    "    def __init__(self, brain_region, dnn_model):\n",
    "        self.brain_region = brain_region\n",
    "        self.dnn_model = dnn_model\n",
    "\n",
    "    def classical_rsa(self, layer, unit_subset=None):\n",
    "        # Compute Pearson similarity matrices for brain and model feature spaces\n",
    "        # and correlate them (classical RSA)\n",
    "        pass\n",
    "\n",
    "    def feature_reweighted_rsa(self, layer, unit_subset=None, train_data_loader=None, test_data_loader=None):\n",
    "        # Fit a sparse, positive-weighted encoding model between the model and brain feature spaces\n",
    "        # using a training set of fMRI stimuli (using sklearn.Lasso(positive=True))\n",
    "        # Then, generate predicted voxel activations over a test set of fMRI stimuli\n",
    "        # The model similarity matrix is computed over these predicted activations\n",
    "        # and correlated with the brain similarity matrix (veRSA)\n",
    "        pass\n",
    "\n",
    "    def best_layer_rsa(self, layers, image_set_1, image_set_2, comparison_method=\"classical_rsa\"):\n",
    "        # Use image_set_1 to compute prediction scores for all layers\n",
    "        # Select the best layer\n",
    "        # Report a final score using image_set_2 in just that layer\n",
    "        pass\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0bed4f39-739a-4202-b757-2647c61ea83f",
   "metadata": {},
   "outputs": [],
   "source": [
    "class GSN:\n",
    "    def __init__(self, brain_region, image_set):\n",
    "        self.brain_region = brain_region\n",
    "        self.image_set = image_set\n",
    "\n",
    "    def compute_noise_ceiling(self):\n",
    "        # Run the GSN pipeline to compute a subject-specific noise ceiling\n",
    "        # Return the signal and noise covariance matrices of the brain data\n",
    "        pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9717f554-6592-4955-8b75-6a7907d664fc",
   "metadata": {},
   "outputs": [],
   "source": [
    "subjects = []\n",
    "brain_regions = []\n",
    "\n",
    "# Main pipeline\n",
    "def main():\n",
    "    # Load different image sets\n",
    "    localizer_images = ImageSet('localizer', localizer_image_paths)\n",
    "    localizer_images.load_images()\n",
    "    localizer_data_loader = DataLoaderWrapper(localizer_images, dnn_model)\n",
    "\n",
    "    probe_images = ImageSet('probe', probe_image_paths)\n",
    "    probe_images.load_images()\n",
    "\n",
    "    fmri_stimuli = ImageSet('fmri_stimuli', fmri_stimuli_paths)\n",
    "    fmri_stimuli.load_images()\n",
    "\n",
    "    imagenet_train = ImageSet('imagenet_train', imagenet_train_paths)\n",
    "    imagenet_train.load_images()\n",
    "\n",
    "    imagenet_val = ImageSet('imagenet_val', imagenet_val_paths)\n",
    "    imagenet_val.load_images()\n",
    "\n",
    "    # Load DNN model\n",
    "    dnn_model = DNNModel(model_name, model_path, model_type)\n",
    "    dnn_model.load_model()\n",
    "    dnn_model.find_selective_units(localizer_images.images)\n",
    "\n",
    "    if dnn_model.model_type == 'self-supervised':\n",
    "        dnn_model.train_linear_probe(imagenet_train.images, imagenet_val.images)\n",
    "\n",
    "    dnn_model.assess_lesioning_impact(imagenet_val.images)\n",
    "\n",
    "    # Load fMRI subject data and process it\n",
    "    fmri_subject = fMRISubject(subject_id, fmri_data_path)\n",
    "    fmri_subject.load_fmri_data()\n",
    "    fmri_subject.find_brain_regions(fmri_stimuli.images)\n",
    "\n",
    "    # Brain-model comparison\n",
    "    comparison = BrainModelComparison(brain_region, dnn_model)\n",
    "    classical_rsa_score = comparison.classical_rsa(layer)\n",
    "    veRSA_score = comparison.feature_reweighted_rsa(layer, train_data_loader=fmri_train_data_loader, test_data_loader=fmri_test_data_loader)\n",
    "    best_layer_score = comparison.best_layer_rsa(layers, image_set_1, image_set_2)\n",
    "    \n",
    "    # GSN noise ceiling computation\n",
    "    gsn = GSN(brain_region, fmri_stimuli)\n",
    "    noise_ceiling, signal_cov, noise_cov = gsn.compute_noise_ceiling()\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "jspbase",
   "language": "python",
   "name": "jspbase"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
